package mdp.algorithm.explore.P;

import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Stack;

import javax.swing.JLabel;
import javax.swing.Timer;

import mdp.algorithm.fastestPath.PathSolver;
import mdp.algorithm.simulator.Maze;
import mdp.algorithm.simulator.Stopwatch;
import mdp.algorithm.simulator.TimerQueue;

public class ExplorationSide implements Runnable{
	
	private Stopwatch s;
	private int robotOrientation;
	private int robotMidPointRow;
	private int robotMidPointCol;
	private Maze maze;
	private JLabel exploreTimeValue;
	private String timeLimit;
	private String tempStr;
	private float tempFloat;
	private float timeLimitFloat;
	private Timer timer;
	private boolean status = false;
	private boolean start;
	int[][] visited = new int[22][17]; //0 mean not visted, 1 means visted
	private boolean goal = false;
	private float percentMap;
	private int speed;
	private int counter=0;
	private int terminateCounter = 00;
	private int terminateCounterPosition = -1; 
	
	public ExplorationSide(Maze mazeMap, JLabel exploreTimeValue, String timeLimit, float percentMap, float speed){
		s = new Stopwatch();
		maze = mazeMap;
		robotOrientation = maze.getRobotOrientation();
		robotMidPointRow = maze.getRobotMidPointRow();
		robotMidPointCol = maze.getRobotMidPointCol();
		
		for(int i=0; i<21; i++){
			for(int j=0; j<16; j++){
				visited[i][j] = 0; 
			}
		}
		this.percentMap = percentMap;
		this.exploreTimeValue = exploreTimeValue;
		System.out.println("perMap" + percentMap);
		System.out.println("Start timeLimit: " + timeLimit);
		int tempTimeLimit = Integer.parseInt(timeLimit.substring(0, 1)) - 1;
		this.timeLimit = tempTimeLimit + timeLimit.substring(1);
		System.out.print(this.timeLimit);
		this.speed =(int)(speed*1000);
	}
	
	public void explorePath(){
		tempStr = timeLimit.substring(0, 1);
		timeLimitFloat = Integer.parseInt(tempStr);
		tempStr = timeLimit.substring(2, 4);
		tempFloat = Float.parseFloat(tempStr) * 1/60;
		timeLimitFloat = timeLimitFloat + tempFloat;
		start = true;
		s.startStopwatchTimer(exploreTimeValue, timeLimitFloat);
		startTimer();
	}

	private void startTimer(){
		timer = new Timer(speed, new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				if(maze.percentageExplored() >= percentMap || exploreTimeValue.getText().equals("0"+timeLimit) || terminateOneRound()){
					stopExplore();
		  			System.out.print("end1");
		  		}
				else{
					if(status){
						explorePathAction();
						status = false;
					}
					else{
						//setExploreAction();
						maze.backupExploration(robotMidPointRow, robotMidPointCol);
						status = true;
					}
		    	}
			}
		});
		timer.start();
	}
	
	private boolean terminateOneRound(){
		if((terminateCounterPosition == 0 && checkStart()) || (terminateCounterPosition == 1 && checkGoal())){
			System.out.println("TERMINATE HEREEEEEEEEEEEEEEEEEEEEEEEEEE");
			return true;
		}
		return false;
	}
	
	public void setExploreAction(){
		maze.esSetExplorationPathAction();
	}
	
	public void explorePathAction(){
		if(!goal)
			goal = checkGoal();
		
		if(start){	
			if(robotMidPointRow==2 || robotMidPointRow==19 || robotMidPointCol==2 || robotMidPointCol==14){
				start = false;
				maze.spinLeftAction();
			}
			else{
				if(counter == 0){
					if(maze.esCheckFrontClear())
						maze.moveForwardAction();
					else{
						maze.spinLeftAction();
						counter--;
					}
				}
				else{
					if(maze.esStartCheckRightClear()){
						maze.spinRightAction();
						if(maze.esCheckFrontClear())
							maze.moveForwardAction();
						counter++;
					}
					else if(maze.esCheckFrontClear()){
						maze.moveForwardAction();
					}
					else{
						maze.spinLeftAction();
						if(maze.esCheckFrontClear())
							maze.moveForwardAction();
						counter--;
					}
				}
			}
		}
		else{
			if(maze.esStartCheckRightClear()){
				maze.spinRightAction();
				if(maze.esCheckFrontClear())
					maze.moveForwardAction();
			}
			else if(maze.esCheckFrontClear()){
				maze.moveForwardAction();
			}
			else if(maze.esStartCheckLeftClear()){
				maze.spinLeftAction();
				if(maze.esCheckFrontClear())
					maze.moveForwardAction();
			}
			else{
				maze.spinRightAction();
				maze.spinRightAction();
				if(maze.esCheckFrontClear())
					maze.moveForwardAction();
			}
		}
		robotMidPointRow = maze.getRobotMidPointRow();
		robotMidPointCol = maze.getRobotMidPointCol();	
		

		if(checkGoal()){
			if(terminateCounter%10 == 0)
				terminateCounter++;
			if(terminateCounter == 11 && terminateCounterPosition==-1)
				terminateCounterPosition = 0;
		}
			
		
		if(checkStart()){
			if(terminateCounter < 10)
				terminateCounter+=10;
			if(terminateCounter == 11 && terminateCounterPosition==-1)
				terminateCounterPosition = 1;
		}
	}
	
	private void stopExplore(){
		Point start = new Point(maze.getRobotMidPointRow(), maze.getRobotMidPointCol());
        maze.startTimer();
        if((maze.checkExplored(2,13)|| maze.checkExplored(3,14)) && maze.checkUnexplored(2,14)){
        	PathSolver ps1 = new PathSolver();
        	Point goal1 = new Point(2,14);
    		ps1.moveRobot(ps1.solvePath(start,goal1,maze,maze.getRobotOrientation()),start,goal1,maze,maze.getRobotOrientation());
        }
        
      //go to start
		Point goal2 = new Point(19,2);
        PathSolver ps2 = new PathSolver();
		ps2.moveRobot(ps2.solvePath(start,goal2,maze,maze.getRobotOrientation()),start,goal2,maze,maze.getRobotOrientation());
        maze.completePath();
		timer.stop();
	}
	public void stopExploreStopwatchTimer(){
		s.stopStopwatchTimer();
		s.resetStopwatchTimer();
	}
	
	public void stopTimer(){
		timer.stop();
	}
	
	private boolean checkGoal(){
		if(robotMidPointRow==2 && robotMidPointCol == 14)
			return true;
		return false;
	}
	
	private boolean checkStart(){
		if(robotMidPointRow==19 && robotMidPointCol == 2)
			return true;
		return false;
	}
	
	@Override
    public void run() {
        // TODO Auto-generated method stub
		explorePath();
    }
}